package tallinn;

import java.util.ArrayList;

import processing.core.PApplet;
import simpleGeom.Grid3DFloat;
import simpleGeom.Line3D;
import simpleGeom.SimpleMCube;
import simpleGeom.Vec3D;
import simpleGui.PCamera3D;

public class SimpleTallin extends PApplet{
Grid3DFloat grid;
float[] closestCells;
ArrayList<Vec3D> vecs=new ArrayList<Vec3D>();
ArrayList<Line3D> lines=new ArrayList<Line3D>();

SimpleMCube smCube;
PCamera3D cam;
public void setup(){
	size(1600,800,OPENGL);
	cam = new PCamera3D(this,0.5f,0.1f);
	grid=new Grid3DFloat(300,30,40);
	grid.dim=1;
	closestCells=new float[300*30*40];
	for (int x=0;x<40;x++){
		for (int y=0;y<2;y++){
			for (int z=0;z<5;z++){
				if (random(1)>0.1f){
				Vec3D v=new Vec3D(x*7.5f+5,y*20+5,z*8+4);
				vecs.add(v);
				}
			}
		}
	}
	Line3D line=new Line3D(100,30,0,110,20,40);
	lines.add(line);
	calculateClosest();
	smCube=new SimpleMCube();
	smCube.marchingCubes(grid.nX, grid.nY, grid.nZ, grid.values, 0.5f, 1, 0, 0, 0, null);
}

public void calculateClosest(){
	for (int i=0;i<grid.values.length;i++){
		grid.values[i]=100000;
	}
	for (int i=0;i<grid.values.length;i++){
		float x=grid.getXFloat(grid.getX(i));
		float y=grid.getYFloat(grid.getY(i));
		float z=grid.getZFloat(grid.getZ(i));
		for (int j=0;j<vecs.size();j++){
			Vec3D v=vecs.get(j);
			float cD=v.dist(x,y,z);
			if (cD<grid.values[i]){
				grid.values[i]=cD;
				closestCells[i]=j;
			}
		}
		for (int j=0;j<lines.size();j++){
			Line3D l=lines.get(j);
			float cD=l.ptLineDist(x, y, z);
			if (cD<grid.values[i]){
				grid.values[i]=cD;
				closestCells[i]=j+vecs.size();
			}
		}
	}
	for (int i=0;i<grid.values.length;i++){
		grid.values[i]=0;
	}
	for (int x=1;x<grid.nX;x++){
		for (int y=1;y<grid.nY;y++){
			for (int z=1;z<grid.nZ;z++){
				int index=grid.getIndex(x, y, z);
				int indexX=grid.getIndex(x-1, y, z);
				int indexY=grid.getIndex(x, y-1, z);
				int indexZ=grid.getIndex(x, y, z-1);
				if (closestCells[index]<vecs.size()){
				if (closestCells[index]!=closestCells[indexX]){
					if (closestCells[indexX]<vecs.size()){
					grid.values[index]=1;
					grid.values[indexX]=1;
					}
				}
				if (closestCells[index]!=closestCells[indexY]){
					if (closestCells[indexY]<vecs.size()){
					grid.values[index]=1;
					grid.values[indexY]=1;
					}
				}
				if (closestCells[index]!=closestCells[indexZ]){
					if (closestCells[indexZ]<vecs.size()){
					grid.values[index]=1;
					grid.values[indexZ]=1;
					}
				}
				}
			}
		}
	}
	for (int x=0;x<grid.nX;x++){
		for (int y=0;y<grid.nY;y++){
			for (int z=0;z<grid.nZ;z++){
				if (x==0||x==grid.nX-1||y==0||z==0||z==grid.nZ-1||y==grid.nY-1){
					int index=grid.getIndex(x, y, z);
					grid.values[index]=0;
				}
			}
		}
	}
}

public void draw(){
	lights();
	cam.apply(g);
	background(0);
	noStroke();
	scale(10);
	
	translate(grid.nX*-0.5f,grid.nY*-0.5f,grid.nZ*-0.5f);
	for (int i=0;i<vecs.size();i++){
		Vec3D v=vecs.get(i);
		pushMatrix();
		translate(v.x,v.y,v.z);
		box(1);
		popMatrix();
	}
	
	smCube.draw(g);
}


}
